<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.9.4"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Flow-IPC: ipc::session::Session_base&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher Class Reference</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr id="projectrow">
  <td id="projectalign">
   <div id="projectname">Flow-IPC<span id="projectnumber">&#160;2.0.0</span>
   </div>
   <div id="projectbrief">Flow-IPC project: Full implementation reference.</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.9.4 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
var searchBox = new SearchBox("searchBox", "search",'Search','.html');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
/* @license-end */
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="namespaceipc.html">ipc</a></li><li class="navelem"><a class="el" href="namespaceipc_1_1session.html">session</a></li><li class="navelem"><a class="el" href="classipc_1_1session_1_1Session__base.html">Session_base</a></li><li class="navelem"><a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html">Graceful_finisher</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="summary">
<a href="#pub-methods">Public Member Functions</a> &#124;
<a href="#pri-attribs">Private Attributes</a> &#124;
<a href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher-members.html">List of all members</a>  </div>
  <div class="headertitle"><div class="title">ipc::session::Session_base&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher Class Reference</div></div>
</div><!--header-->
<div class="contents">

<p>Optional to use by subclasses, this operates a simple state machine that carries out a graceful-session-end handshake procedure.  
 <a href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#details">More...</a></p>

<p><code>#include &lt;<a class="el" href="session__base_8hpp_source.html">session_base.hpp</a>&gt;</code></p>
<div class="dynheader">
Inheritance diagram for ipc::session::Session_base&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classipc_1_1session_1_1Session__base_1_1Graceful__finisher__inherit__graph.svg" width="310" height="143"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
<center><span class="legend">[<a href="graph_legend.html">legend</a>]</span></center></div>
<div class="dynheader">
Collaboration diagram for ipc::session::Session_base&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classipc_1_1session_1_1Session__base_1_1Graceful__finisher__coll__graph.svg" width="1911" height="1091"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
<center><span class="legend">[<a href="graph_legend.html">legend</a>]</span></center></div>
<table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="pub-methods" name="pub-methods"></a>
Public Member Functions</h2></td></tr>
<tr class="memitem:a28a9c414cee99b868b2cd291cee24ea0"><td class="memItemLeft" align="right" valign="top">&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#a28a9c414cee99b868b2cd291cee24ea0">Graceful_finisher</a> (flow::log::Logger *logger_ptr, <a class="el" href="classipc_1_1session_1_1Session__base.html">Session_base</a> *this_session, flow::async::Single_thread_task_loop *async_worker, <a class="el" href="classipc_1_1session_1_1Session__base.html#a26d038e14e3c0e461e76de88c4ce76c5">Master_structured_channel</a> *master_channel)</td></tr>
<tr class="memdesc:a28a9c414cee99b868b2cd291cee24ea0"><td class="mdescLeft">&#160;</td><td class="mdescRight">You must invoke this ctor (instantiate us) if and only if synchronized dtor execution is indeed required; and <code>*this_session</code> has just reached PEER state.  <a href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#a28a9c414cee99b868b2cd291cee24ea0">More...</a><br /></td></tr>
<tr class="separator:a28a9c414cee99b868b2cd291cee24ea0"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:af7c591a4b774ae52603fa6d890e369f1"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#af7c591a4b774ae52603fa6d890e369f1">on_master_channel_hosed</a> ()</td></tr>
<tr class="memdesc:af7c591a4b774ae52603fa6d890e369f1"><td class="mdescLeft">&#160;</td><td class="mdescRight">Must be invoked if the <code>*_session_impl</code> detects that the master channel has emitted channel-hosing error.  <a href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#af7c591a4b774ae52603fa6d890e369f1">More...</a><br /></td></tr>
<tr class="separator:af7c591a4b774ae52603fa6d890e369f1"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:af441f45ce1ed7b890c3ab77d959f8830"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#af441f45ce1ed7b890c3ab77d959f8830">on_dtor_start</a> ()</td></tr>
<tr class="memdesc:af441f45ce1ed7b890c3ab77d959f8830"><td class="mdescLeft">&#160;</td><td class="mdescRight">The reason <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html" title="Optional to use by subclasses, this operates a simple state machine that carries out a graceful-sessi...">Graceful_finisher</a> exists, this method must be called at the start of <code>*_session_impl</code> dtor; and will block until it is appropriate to let that dtor proceed to shut down the <code>*_session_impl</code>.  <a href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#af441f45ce1ed7b890c3ab77d959f8830">More...</a><br /></td></tr>
<tr class="separator:af441f45ce1ed7b890c3ab77d959f8830"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="pri-attribs" name="pri-attribs"></a>
Private Attributes</h2></td></tr>
<tr class="memitem:acb037930b23240ecf8975e65f50f3927"><td class="memItemLeft" align="right" valign="top"><a class="el" href="classipc_1_1session_1_1Session__base.html">Session_base</a> *const&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#acb037930b23240ecf8975e65f50f3927">m_this_session</a></td></tr>
<tr class="memdesc:acb037930b23240ecf8975e65f50f3927"><td class="mdescLeft">&#160;</td><td class="mdescRight">The containing <a class="el" href="classipc_1_1session_1_1Session__base.html" title="Internal type containing data and types common to internal types Server_session_impl and Client_sessi...">Session_base</a>. It shall exist until <code>*this</code> is gone.  <a href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#acb037930b23240ecf8975e65f50f3927">More...</a><br /></td></tr>
<tr class="separator:acb037930b23240ecf8975e65f50f3927"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a5de1dea5af9f0ef5558e91ff6484e68d"><td class="memItemLeft" align="right" valign="top">flow::async::Single_thread_task_loop *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#a5de1dea5af9f0ef5558e91ff6484e68d">m_async_worker</a></td></tr>
<tr class="memdesc:a5de1dea5af9f0ef5558e91ff6484e68d"><td class="mdescLeft">&#160;</td><td class="mdescRight">The containing <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code> thread W loop. It shall exist until <code>*this</code> is gone.  <a href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#a5de1dea5af9f0ef5558e91ff6484e68d">More...</a><br /></td></tr>
<tr class="separator:a5de1dea5af9f0ef5558e91ff6484e68d"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a8dd106d9ac3223737dac58d0b056367b"><td class="memItemLeft" align="right" valign="top"><a class="el" href="classipc_1_1session_1_1Session__base.html#a26d038e14e3c0e461e76de88c4ce76c5">Master_structured_channel</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#a8dd106d9ac3223737dac58d0b056367b">m_master_channel</a></td></tr>
<tr class="memdesc:a8dd106d9ac3223737dac58d0b056367b"><td class="mdescLeft">&#160;</td><td class="mdescRight">The containing <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code> master channel. It shall exist until <code>*this</code> is gone.  <a href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#a8dd106d9ac3223737dac58d0b056367b">More...</a><br /></td></tr>
<tr class="separator:a8dd106d9ac3223737dac58d0b056367b"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ab1548d77913d3e99e4f30e1dd46f8d86"><td class="memItemLeft" align="right" valign="top">boost::promise&lt; void &gt;&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#ab1548d77913d3e99e4f30e1dd46f8d86">m_opposing_session_done</a></td></tr>
<tr class="memdesc:ab1548d77913d3e99e4f30e1dd46f8d86"><td class="mdescLeft">&#160;</td><td class="mdescRight">A promise whose fulfillment is a necessary and sufficient condition for <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#af441f45ce1ed7b890c3ab77d959f8830" title="The reason Graceful_finisher exists, this method must be called at the start of *_session_impl dtor; ...">on_dtor_start()</a> returning (letting <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code> dtor complete).  <a href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#ab1548d77913d3e99e4f30e1dd46f8d86">More...</a><br /></td></tr>
<tr class="separator:ab1548d77913d3e99e4f30e1dd46f8d86"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table>
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
<div class="textblock"><div class="compoundTemplParams">template&lt;schema::MqType S_MQ_TYPE_OR_NONE, bool S_TRANSMIT_NATIVE_HANDLES, typename Mdt_payload&gt;<br />
class ipc::session::Session_base&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher</div><p >Optional to use by subclasses, this operates a simple state machine that carries out a graceful-session-end handshake procedure. </p>
<p >A particular <a class="el" href="classipc_1_1session_1_1Client__session__impl.html" title="Internal, non-movable pImpl-lite implementation of Client_session_mv class template.">Client_session_impl</a> and symmetrically its opposing <a class="el" href="classipc_1_1session_1_1Server__session__impl.html" title="Internal, non-movable pImpl-lite implementation of Server_session_mv class template.">Server_session_impl</a> shall instantiate a <code>*this</code> internally and invoke its methods on certain events, as described in their contracts.</p>
<p >Now we explain what we're solving (Rationale); then how we solve it (Design). The latter is much simpler, we think, to understand then the former. Hence apologies in advance for the length of "Rationale" section.</p>
<h3>Rationale</h3>
<p >Consider a particular <a class="el" href="classipc_1_1session_1_1Client__session__impl.html" title="Internal, non-movable pImpl-lite implementation of Client_session_mv class template.">Client_session_impl</a> + <a class="el" href="classipc_1_1session_1_1Server__session__impl.html" title="Internal, non-movable pImpl-lite implementation of Server_session_mv class template.">Server_session_impl</a> class/object pair, A and B. In this case &ndash; which is somewhat unusual (relative to most internal <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code> algorithms) but in a good, simplifying way &ndash; it does not matter which is A and which is B. So let's say A is us and B is the opposing guy.</p>
<p >Also, for now, assume these are just the vanilla ones: <a class="el" href="classipc_1_1session_1_1Client__session__impl.html" title="Internal, non-movable pImpl-lite implementation of Client_session_mv class template.">session::Client_session_impl</a> and <a class="el" href="classipc_1_1session_1_1Server__session__impl.html" title="Internal, non-movable pImpl-lite implementation of Server_session_mv class template.">session::Server_session_impl</a>; not SHM-enabled &ndash; no SHM arenas in play.</p>
<p >Consider what happens when A dtor is invoked, in PEER state. The session ends, and the session-end trigger is us. Without <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html" title="Optional to use by subclasses, this operates a simple state machine that carries out a graceful-sessi...">Graceful_finisher</a> what happens is as follows. The <a class="el" href="classipc_1_1session_1_1Session__base.html#a26d038e14e3c0e461e76de88c4ce76c5" title="The (internally used) session master channel is a transport::struc::Channel of this concrete type.">Master_structured_channel</a> in <code>*this</code> is closed; and then <code>*this</code> goes away altogether right away/synchronously. Soon B's <a class="el" href="classipc_1_1session_1_1Session__base.html#a26d038e14e3c0e461e76de88c4ce76c5" title="The (internally used) session master channel is a transport::struc::Channel of this concrete type.">Master_structured_channel</a> throws the graceful-close error; B itself correctly interprets this as a session-end trigger; and B throws an error via the <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code> error handler. Now, the user is told by docs they informally <em>should</em> destroy the B (invoke its dtor) ASAP, but nothing is formally forcing them to; it can sit around. It will never accept channel passive-opens; <code>open_channel()</code> will no-op / return null; etc. It is useless, but it can stay around. Eventually B dtor will be invoked by user; it'll basically clean up data structures, and that's that.</p>
<p >There is no problem there: A dtor and B dtor can run at quite different times, or more precisely B dtor can run much later than A dtor which triggered session-end. Nothing bad happens.</p>
<p >Now we'll discuss this in specific terms around actual <code>Client/Server_session_impl</code> variants that do exist at this time. We could try to be formal and general, but it's easier to just be specific for exposition purposes.</p>
<p >Take, now, the <a class="el" href="classipc_1_1session_1_1shm_1_1classic_1_1Client__session__impl.html" title="Core internally-used implementation of shm::classic::Client_session: it is to the latter what its pub...">shm::classic::Client_session_impl</a> <a class="el" href="classipc_1_1session_1_1shm_1_1classic_1_1Server__session__impl.html" title="Core internally-used implementation of shm::classic::Server_session: it is to the latter what its pub...">shm::classic::Server_session_impl</a> variants. The above generally holds, but there are now SHM arenas in play. We can forget about the app-scope arenas right off the bat: That guy stays around as long as the <code><a class="el" href="classipc_1_1session_1_1Session__server.html" title="To be instantiated typically once in a given process, an object of this type asynchronously listens f...">Session_server</a></code> does, and that guy is formally required to be around until all child <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code>s have been destroyed. So only session-scope arenas &ndash; the ones inside A and B &ndash; are relevant. In fact, for SHM-classic there really is only <em>one</em> arena: A holds a handle to it (<code>a.session_shm()</code> points to it), and B does so symmetrically.</p>
<p >Now reconsider the scenario above: A dtor runs. (Insert vanilla <code>*_session_impl</code> text from above here.) Also, though, A dtor will remove the underlying SHM-pool by its name. (This is possibly a lie. This is technically so, only if A is a <code><a class="el" href="classipc_1_1session_1_1Server__session__impl.html" title="Internal, non-movable pImpl-lite implementation of Server_session_mv class template.">Server_session_impl</a></code>; we've assigned the task to the server side as of this writing. But this technicality is irrelevant: unlinking the SHM-pool doesn't blow up the other side's access to the arena; it remains in RAM until that guy closes. So just bear with us here.) Then indeed B dtor can run sometime later. Is there a problem? For SHM-classic, which is what we're discussing, no: The arena &ndash; 1 shared SHM-pool in this case &ndash; stays alive, until B's handle gets closed by B dtor. What about allocations/deallocations? No problem there either: By contract, the A user <em>must</em> drop all cross-process <code>shared_ptr</code> handles to objects that it owns, before invoking A dtor; so A is fine, and the internal cross-process ref-counts for each A-held object get decremented by 1, due to the <code>shared_ptr</code> handles being nullified by the user by contract. (For context: The guided manual <code>session_app_org</code> page describes to the reader how to structure their program, so that this is guaranteed. In short, declare the object handle data members in their code after the <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code> data member, so they get deinitialized in the reverse order, in the user's hypothetical recommended <code>App_session</code> class.) Isn't there a problem in B, though? No: the B user shall drop <em>its</em> <code>shared_ptr</code> handles, before invoking B dtor; this will drop their internal cross-process ref-counts to 0; at which point shm::Pool_arena logic will deallocate those objects. Deallocation is entirely distributed between A and B; in this scenario B's handles just happen to live longer and therefore happen to be the ones triggering the deallocations &ndash; by the B process itself, synchronously. A is not "in charge" of deallocations of anything in any special way; it doesn't matter which process originally allocated a given object either. That's the beauty/simplicity of SHM-classic. (There are of course trade-offs in play; this is worse for segregation/safety... see Manual and such.)</p>
<p >Now we come to the point. Consider <a class="el" href="classipc_1_1session_1_1shm_1_1arena__lend_1_1jemalloc_1_1Client__session__impl.html" title="Core internally-used implementation of shm::arena_lend::jemalloc::Client_session: it is to the latter...">session::shm::arena_lend::jemalloc::Client_session_impl</a> and <code><a class="el" href="classipc_1_1session_1_1Server__session__impl.html" title="Internal, non-movable pImpl-lite implementation of Server_session_mv class template.">Server_session_impl</a></code>. There <em>is</em> a problem. Interestingly this time it really does <em>not</em> matter whether A is server or client-side. In SHM-jemalloc the session-scope arenas are not 1 but 2: A has an arena, from which process A can allocate, and in which process A shall deallocate. B has an arena, from which process B can allocate, and in which process B shall deallocate. If B borrows object X from A, and is later done with it &ndash; the <code>shared_ptr</code> local ref-count reached 0 &ndash; SHM-jemalloc-arranged <code>shared_ptr</code> deleter will send an internal message over a special channel to A. A will deallocate X once that has occurred, <em>and</em> any A-held <code>shared_ptr</code> group for X has also reached ref-count 0 (which may have happened before, or it may happen later). Exactly the same is true of A borrowing from B, conversely/symmetrically.</p>
<p >The problem is this: Suppose B holds a borrowed handle X (to an A-allocated object). Now A dtor runs; its <code>.session_shm()</code> arena &ndash; its constitutent SHM-pools! &ndash; is destroyed. That in itself shouldn't be a problem; again B presumably holds a SHM-pool handle, so it won't just disappear from RAM under it. I (ygoldfel) am somewhat fuzzy on what exactly happens (not being the direct author of SHM-jemalloc), but basically as I understand it, in destroying the arena, a bunch of jemalloc deinit steps execute; perhaps heap-marker data structures are modified all over the place... it's chaos. The bottom line is: A arena gets mangled, so the B-held borrowed handle X has a high chance of pointing, now, to garbage: Not unmapped garbage; not into a SHM-pool that's magically gone &ndash; it's still there &ndash; so there's not necessarily a SEGV as a result; just garbage in the ~sense of accessing <code>free()</code>d (not un-<code>mmap()</code>ped) memory.</p>
<p >(Update: I've spoken to the SHM-jemalloc author echan, and the above is basically right with a couple clarifications. It's not so much that the arena object being destroyed is the issue; in fact that in itself would be handled gracefully by SHM-jemalloc innards; they will keep the arena around, even if the outer object goes away (or more precisely as of this writing the arena-handle &ndash; a <code>shared_ptr</code> &ndash; does), while it knows things are pointing into it, even borrowed things in another process. Really it's the fact that we kill the <em>channel</em> it uses to communicate with the borrower process: the arena is told there's nothing out there pointing into it: locally the user has to have dropped all constructed-object handles; and the borrower process it no longer has a way of contacting it; so it assumes tgat guy's done/gone, as are all the borrowed handles in it. That clarification doesn't change the situation though: Whether it's the SHM-jemalloc-session, or the SHM-jemalloc-session-used-channel, or the SHM-jemalloc-arena going away that makes borrowed objects unusable &ndash; they are unusable, is the bottom line.)</p>
<p >All that is to say: A dtor runs; and user handle to object X in B instantly becomes unusable. For example, I (ygoldfel) have observed a simple thing: A SHM-jemalloc-backed <a class="el" href="classipc_1_1transport_1_1struc_1_1Msg__in.html" title="A structured in-message instance suitable as received and emittable (to user) by struc::Channel.">transport::struc::Msg_in</a> received from A, in B, was absolutely fine. Then it was running a long tight-loop verification of its contents &ndash; verifying hashes of millions of X-pointed objects in SHM, preventing B dtor from running. Meanwhile, A in a test program had nothing more to do and ran A dtor (closed session). Suddenly, the hash-verifier code in the tight loop was hitting hash mismatches, throwing capnp exceptions in trying to traverse the message, and so on.</p>
<p >What this means, ultimately, is straightforward: A dtor must not destroy its SHM-jemalloc arena (as accessible normally through <code>.session_shm()</code>), until not just <em>A</em> user has dropped all its object <code>shared_ptr</code> handles; but <em>B</em> user &ndash; that's in the other process, B &ndash; has as well! How can we enforce this, though? One approach is to just put it on the user: Tell them that they must design their protocol in such a way as to arrange some kind of handshake, as appropriate, beyond which each side knows for a fact that the session objects, and therefore arenas, are safe to destroy.</p>
<p >We don't want to do that for obvious reasons. What we already tell them should be sufficient: If you get a session-hosing error handler execution in your <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code>, then don't use that <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code>, and you should destroy it ASAP, for it is useless, and the other side's <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code> is not long for this life. If they listen to this, then A dtor will soon be followed by B dtor anyway. It might be delayed by some long tight-loop operation such as the test-program hash-verifying scenario above, but generally users avoid such things; and when they don't they can expect other things to get blocked, possibly in the opposing process. Subjectively, weird blocking &ndash; caused by the other side acting pathologically &ndash; is a lot more acceptable at session-start or session-end than something like that occuring mid-session.</p>
<p >So what's the exact proposal? It's this: If A dtor begins executing, it must first block until it knows B dtor has begun executing; but once it does know that, it knows that all B-held object handles have been dropped &ndash; which is what we want. (It would be possible for B user to indicate it some other way &ndash; another API call, short of destruction &ndash; but that seems unnecessarily complex/precious. If the session is finished, then there's no reason to keep the <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code> object around = the overall policy we've pursued so far, so why make exceptions for this?)</p>
<p >To be clear, this means certain behavior by B user can cause A dtor to block. We can explain this in the docs, of course, but perhaps much more effective is to make it clear in the logs: say the wait begins here and what it'll take for it to end; and say when it has ended and why.</p>
<p >Also to be clear, <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html" title="Optional to use by subclasses, this operates a simple state machine that carries out a graceful-sessi...">Graceful_finisher</a> should be used only in <code>*_session_impl</code> pairs that actually have this problem; so of the 3 pairs we've discussed above &ndash; only SHM-jemalloc's ones. The others can completely forego all this.</p>
<dl class="todo"><dt><b><a class="el" href="todo.html#_todo000034">Todo:</a></b></dt><dd>Consider how to avoid having SHM-jemalloc <a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a> mechanism require one side's <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code> dtor await (and possibly block) the start of the opposing side's <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code> dtor, before it can proceed. The reason it does this today is above this to-do in the code. The blocking is not too bad &ndash; if the user's applications are properly written, it will not occur, and the existing logging should make clear why it happens, if it happens; but it's still not ideal. There are a couple known mitigating approaches, and at least 1 ticket covering them is likely filed. (Either way the <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html" title="Optional to use by subclasses, this operates a simple state machine that carries out a graceful-sessi...">Graceful_finisher</a> mechanism could then be removed probably.) To summarize them: 1, there can be a mechanism deep inside SHM-jemalloc code that gives (arbitrarily long, configurable) grace period for known borrowed objects whose session channels have closed before those objects were returned; this was echan's idea on this topic. Once the grace period is reached, it would act as-if they got returned then (so in the above scenario the arena could get jemalloc-deinitialized and all). If program needs to exit, it could either block until the end of the grace period or... who knows? 2, something similar could be done about the SHM-internal-use channel: do not close it but add it to some list of such channels; they would be finally closed upon detection of the other side's <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code> dtor being reached, in some background thread somewhere. (On 2nd thought this sounds a lot like <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html" title="Optional to use by subclasses, this operates a simple state machine that carries out a graceful-sessi...">Graceful_finisher</a> &ndash; but for this particular internal-use channel only. The code here would only get more complex, thought maybe not too much more. However, it would resolve the observed <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code>-dtor-blocking user-visible issue, at least until the delayed-channel-death process had to exit entirely.) Beyond these basic ideas (which could even perhaps be combined) this requires some thinking; it is an interesting problem. In the meantime the dtor-cross-process-barrier-of-sorts existing solution is pretty decent.</dd></dl>
<h3>Design / how to use</h3>
<p >How to use: Subclass shall create a <code>*this</code> if and only if the feature is required; it shall call its methods and ctor on certain events, as prescribed in their doc headers.</p>
<p >Design: All this assumes PEER state. Now:</p>
<p >Again let's say we're A, and they're B &ndash; and just like we are. Our goal is to ensure A dtor, at its start, blocks until B dtor has started executing; and to give their side the information necessary to do the same. That's <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#af441f45ce1ed7b890c3ab77d959f8830" title="The reason Graceful_finisher exists, this method must be called at the start of *_session_impl dtor; ...">on_dtor_start()</a>: the method that'll do the blocking; when it returns the dtor of subclass can proceed. So what's needed for <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#af441f45ce1ed7b890c3ab77d959f8830" title="The reason Graceful_finisher exists, this method must be called at the start of *_session_impl dtor; ...">on_dtor_start()</a> to <code>return</code>? One, A dtor has to have started &ndash; but that's true by the contract of when the method is called; two, B dtor has to have started. How do we get informed of the latter? Answer: B sends a special message along the <a class="el" href="classipc_1_1session_1_1Session__base.html#a26d038e14e3c0e461e76de88c4ce76c5" title="The (internally used) session master channel is a transport::struc::Channel of this concrete type.">Master_structured_channel</a>, from its own <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#af441f45ce1ed7b890c3ab77d959f8830" title="The reason Graceful_finisher exists, this method must be called at the start of *_session_impl dtor; ...">on_dtor_start()</a>. Naturally, we do the same &ndash; in full-duplex fashion in a sense &ndash; so that they can use the same logic. So then the steps in <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#af441f45ce1ed7b890c3ab77d959f8830" title="The reason Graceful_finisher exists, this method must be called at the start of *_session_impl dtor; ...">on_dtor_start()</a> are:</p><ol type="1">
<li>Send <code>GracefulSessionEnd</code> message to B, if possible (<a class="el" href="classipc_1_1session_1_1Session__base.html#a26d038e14e3c0e461e76de88c4ce76c5" title="The (internally used) session master channel is a transport::struc::Channel of this concrete type.">Master_structured_channel</a> is up, and the send op doesn't return failure).</li>
<li>Perform <code>m_opposing_session_done.get_future().wait()</code>, where <code>m_opposing_session_done</code> is a <code>promise&lt;void&gt;</code> that shall be fulfilled on these events (and only if it hasn't already been fulfilled before):<ul>
<li>The <a class="el" href="classipc_1_1session_1_1Session__base.html#a26d038e14e3c0e461e76de88c4ce76c5" title="The (internally used) session master channel is a transport::struc::Channel of this concrete type.">Master_structured_channel</a> has received <code>GracefulSessionEnd</code> <em>from</em> B.</li>
<li>The <a class="el" href="classipc_1_1session_1_1Session__base.html#a26d038e14e3c0e461e76de88c4ce76c5" title="The (internally used) session master channel is a transport::struc::Channel of this concrete type.">Master_structured_channel</a> has emitted a channel-hosing error.</li>
</ul>
</li>
</ol>
<p >Notes:</p><ul>
<li>The mainstream case is receiving <code>GracefulSessionEnd</code>: In normal operation, with no acts of god, we will no longer destroy the session-master-channel, until returning from <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#af441f45ce1ed7b890c3ab77d959f8830" title="The reason Graceful_finisher exists, this method must be called at the start of *_session_impl dtor; ...">on_dtor_start()</a>.<ul>
<li>This could happen after the <code>.wait()</code> starts &ndash; meaning A dtor indeed ran before B dtor (our side is the one triggering session-end).</li>
<li>It could just as easily happen <em>before</em> the <code>.wait()</code> starts &ndash; meaning the reverse. Then <code>.wait()</code> will return immediately.</li>
</ul>
</li>
<li>Of course who knows what's going on &ndash; the <a class="el" href="classipc_1_1session_1_1Session__base.html#a26d038e14e3c0e461e76de88c4ce76c5" title="The (internally used) session master channel is a transport::struc::Channel of this concrete type.">Master_structured_channel</a> could still go down without the <code>GracefulSessionEnd</code>. Is it really right to treat this the same, and let <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#af441f45ce1ed7b890c3ab77d959f8830" title="The reason Graceful_finisher exists, this method must be called at the start of *_session_impl dtor; ...">on_dtor_start()</a> return? Answer: Yes. Firstly, there's hardly any other choice: the channel's dead; there's no other way of knowing what to wait for; and we can't just sit there cluelessly. But more to the point, this means it's a <em>not</em>-graceful scenario: <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html" title="Optional to use by subclasses, this operates a simple state machine that carries out a graceful-sessi...">Graceful_finisher</a> can't hope to deal with it and can only proceed heuristically. This is not networking; so we should have a pretty good level of predictability at any rate.</li>
</ul>
<p >Last but not least consider that by delaying the destruction of the <a class="el" href="classipc_1_1session_1_1Session__base.html#a26d038e14e3c0e461e76de88c4ce76c5" title="The (internally used) session master channel is a transport::struc::Channel of this concrete type.">Master_structured_channel</a> until after the dtor has started (assuming no channel-hosing acts of god), we've changed something: The error handler shall no longer inform the user of a session-end trigger from the other side! Left alone this way, we've broken the whole system by introducing a chicken-egg paradox: We don't let our user be informed of the session-end trigger when would normally, so they won't call our dtor; but because they won't call our dtor, we'll never reach the point where the channel would get hosed and we'd know the inform the user. How to fix this? The answer is pretty obvious: Receiving the <code>GracefulSessionEnd</code> shall now trigger a special graceful-session-end error. Naturally this would only be usefully emitted if we're not in the dtor yet. So the latter situation should kick-off the user invoking our dtor sometime soon, hopefully; we'll send our <code>GracefulSessionEnd</code> to them; and so on. </p>

<p class="definition">Definition at line <a class="el" href="session__base_8hpp_source.html#l00575">575</a> of file <a class="el" href="session__base_8hpp_source.html">session_base.hpp</a>.</p>
</div><h2 class="groupheader">Constructor &amp; Destructor Documentation</h2>
<a id="a28a9c414cee99b868b2cd291cee24ea0" name="a28a9c414cee99b868b2cd291cee24ea0"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a28a9c414cee99b868b2cd291cee24ea0">&#9670;&nbsp;</a></span>Graceful_finisher()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;schema::MqType S_MQ_TYPE_OR_NONE, bool S_TRANSMIT_NATIVE_HANDLES, typename Mdt_payload &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname"><a class="el" href="classipc_1_1session_1_1Session__base.html">ipc::session::Session_base</a>&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher::Graceful_finisher </td>
          <td>(</td>
          <td class="paramtype">flow::log::Logger *&#160;</td>
          <td class="paramname"><em>logger_ptr</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="classipc_1_1session_1_1Session__base.html">Session_base</a> *&#160;</td>
          <td class="paramname"><em>this_session</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">flow::async::Single_thread_task_loop *&#160;</td>
          <td class="paramname"><em>async_worker</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="classipc_1_1session_1_1Session__base.html#a26d038e14e3c0e461e76de88c4ce76c5">Master_structured_channel</a> *&#160;</td>
          <td class="paramname"><em>master_channel</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">explicit</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>You must invoke this ctor (instantiate us) if and only if synchronized dtor execution is indeed required; and <code>*this_session</code> has just reached PEER state. </p>
<p >Invoke from thread W only.</p>
<h3>How <code>master_channel</code> shall be touched by <code>*this</code></h3>
<p >We're being very explicit about this, since there's some inter-class private-state sharing going on... generally not the most stable or stylistically-amazing situation....</p><ul>
<li>This ctor will <code>.expect_msg(GRACEFUL_SESSION_END)</code>, so we can detect its arrival and mark it down as needed and possibly invoke <code>this_session-&gt;<a class="el" href="classipc_1_1session_1_1Session__base.html#a7f9e67dccbab4f3191734c2834bafb63" title="Marks this session as hosed for (truthy) reason err_code; and synchronously invokes on-error handler;...">hose()</a></code> to report it to the user. Hence there's no method you'll need to call nor any setup like this needed on your part.</li>
<li><a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#af441f45ce1ed7b890c3ab77d959f8830" title="The reason Graceful_finisher exists, this method must be called at the start of *_session_impl dtor; ...">on_dtor_start()</a> will attempt to send <code>GracefulSessionEnd</code> to the opposing <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html" title="Optional to use by subclasses, this operates a simple state machine that carries out a graceful-sessi...">Graceful_finisher</a>.</li>
</ul>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">logger_ptr</td><td>Logger to use for logging subsequently. (Maybe <code><a class="el" href="classipc_1_1session_1_1Session__base.html" title="Internal type containing data and types common to internal types Server_session_impl and Client_sessi...">Session_base</a></code> should just subclass <code>Log_context</code> for all os us? Add to-do?) </td></tr>
    <tr><td class="paramname">this_session</td><td>The containing <a class="el" href="classipc_1_1session_1_1Session__base.html" title="Internal type containing data and types common to internal types Server_session_impl and Client_sessi...">Session_base</a>. </td></tr>
    <tr><td class="paramname">async_worker</td><td>The thread W of the containing <code>*_session_impl</code>. <code>GracefulSessionEnd</code> handler is at least partially invoked there (<code>hose(...)</code>); and <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#af441f45ce1ed7b890c3ab77d959f8830" title="The reason Graceful_finisher exists, this method must be called at the start of *_session_impl dtor; ...">on_dtor_start()</a> posts onto it. </td></tr>
    <tr><td class="paramname">master_channel</td><td>The containing <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code> master channel. The pointee must exist until <code>*this</code> <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html" title="Optional to use by subclasses, this operates a simple state machine that carries out a graceful-sessi...">Graceful_finisher</a> is gone. </td></tr>
  </table>
  </dd>
</dl>

<p class="definition">Definition at line <a class="el" href="session__base_8hpp_source.html#l01070">1070</a> of file <a class="el" href="session__base_8hpp_source.html">session_base.hpp</a>.</p>

<p class="reference">References <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02062">ipc::transport::struc::Channel&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::expect_msg()</a>, <a class="el" href="session__base_8hpp_source.html#l00937">ipc::session::Session_base&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::hose()</a>, <a class="el" href="session__base_8hpp_source.html#l00946">ipc::session::Session_base&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::hosed()</a>, <a class="el" href="session__base_8hpp_source.html#l00634">ipc::session::Session_base&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher::m_async_worker</a>, <a class="el" href="session__base_8hpp_source.html#l00637">ipc::session::Session_base&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher::m_master_channel</a>, <a class="el" href="session__base_8hpp_source.html#l00647">ipc::session::Session_base&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher::m_opposing_session_done</a>, <a class="el" href="session__base_8hpp_source.html#l00631">ipc::session::Session_base&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher::m_this_session</a>, and <a class="el" href="namespaceipc_1_1session_1_1error.html#a0708d4bec9ae853f4d7e3d7822fc8f2fa24eaed39f149e32f6ceaad54d24f8759">ipc::session::error::S_SESSION_FINISHED</a>.</p>
<div class="dynheader">
Here is the call graph for this function:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classipc_1_1session_1_1Session__base_1_1Graceful__finisher_a28a9c414cee99b868b2cd291cee24ea0_cgraph.svg" width="360" height="167"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
</div>

</div>
</div>
<h2 class="groupheader">Member Function Documentation</h2>
<a id="af441f45ce1ed7b890c3ab77d959f8830" name="af441f45ce1ed7b890c3ab77d959f8830"></a>
<h2 class="memtitle"><span class="permalink"><a href="#af441f45ce1ed7b890c3ab77d959f8830">&#9670;&nbsp;</a></span>on_dtor_start()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;schema::MqType S_MQ_TYPE_OR_NONE, bool S_TRANSMIT_NATIVE_HANDLES, typename Mdt_payload &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">void <a class="el" href="classipc_1_1session_1_1Session__base.html">ipc::session::Session_base</a>&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher::on_dtor_start</td>
        </tr>
      </table>
</div><div class="memdoc">

<p>The reason <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html" title="Optional to use by subclasses, this operates a simple state machine that carries out a graceful-sessi...">Graceful_finisher</a> exists, this method must be called at the start of <code>*_session_impl</code> dtor; and will block until it is appropriate to let that dtor proceed to shut down the <code>*_session_impl</code>. </p>
<p >Invoke from thread U, not thread W. </p>

<p class="definition">Definition at line <a class="el" href="session__base_8hpp_source.html#l01126">1126</a> of file <a class="el" href="session__base_8hpp_source.html">session_base.hpp</a>.</p>

<p class="reference">Referenced by <a class="el" href="ipc__session_2src_2ipc_2session_2detail_2client__session__impl_8hpp_source.html#l00964">ipc::session::Client_session_impl&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload, S_SHM_TYPE_OR_NONE, S_GRACEFUL_FINISH_REQUIRED_V &gt;::dtor_async_worker_stop()</a>, and <a class="el" href="ipc__session_2src_2ipc_2session_2detail_2server__session__impl_8hpp_source.html#l00717">ipc::session::Server_session_impl&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload, S_SHM_TYPE_OR_NONE, S_SHM_MAX_HNDL_SZ, S_GRACEFUL_FINISH_REQUIRED_V &gt;::dtor_async_worker_stop()</a>.</p>
<div class="dynheader">
Here is the caller graph for this function:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classipc_1_1session_1_1Session__base_1_1Graceful__finisher_af441f45ce1ed7b890c3ab77d959f8830_icgraph.svg" width="378" height="131"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
</div>

</div>
</div>
<a id="af7c591a4b774ae52603fa6d890e369f1" name="af7c591a4b774ae52603fa6d890e369f1"></a>
<h2 class="memtitle"><span class="permalink"><a href="#af7c591a4b774ae52603fa6d890e369f1">&#9670;&nbsp;</a></span>on_master_channel_hosed()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;schema::MqType S_MQ_TYPE_OR_NONE, bool S_TRANSMIT_NATIVE_HANDLES, typename Mdt_payload &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">void <a class="el" href="classipc_1_1session_1_1Session__base.html">ipc::session::Session_base</a>&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher::on_master_channel_hosed</td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Must be invoked if the <code>*_session_impl</code> detects that the master channel has emitted channel-hosing error. </p>
<p >Invoke from thread W. </p>

<p class="definition">Definition at line <a class="el" href="session__base_8hpp_source.html#l01110">1110</a> of file <a class="el" href="session__base_8hpp_source.html">session_base.hpp</a>.</p>

</div>
</div>
<h2 class="groupheader">Member Data Documentation</h2>
<a id="a5de1dea5af9f0ef5558e91ff6484e68d" name="a5de1dea5af9f0ef5558e91ff6484e68d"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a5de1dea5af9f0ef5558e91ff6484e68d">&#9670;&nbsp;</a></span>m_async_worker</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;schema::MqType S_MQ_TYPE_OR_NONE, bool S_TRANSMIT_NATIVE_HANDLES, typename Mdt_payload &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">flow::async::Single_thread_task_loop* <a class="el" href="classipc_1_1session_1_1Session__base.html">ipc::session::Session_base</a>&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher::m_async_worker</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">private</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>The containing <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code> thread W loop. It shall exist until <code>*this</code> is gone. </p>

<p class="definition">Definition at line <a class="el" href="session__base_8hpp_source.html#l00634">634</a> of file <a class="el" href="session__base_8hpp_source.html">session_base.hpp</a>.</p>

<p class="reference">Referenced by <a class="el" href="session__base_8hpp_source.html#l01070">ipc::session::Session_base&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher::Graceful_finisher()</a>.</p>

</div>
</div>
<a id="a8dd106d9ac3223737dac58d0b056367b" name="a8dd106d9ac3223737dac58d0b056367b"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a8dd106d9ac3223737dac58d0b056367b">&#9670;&nbsp;</a></span>m_master_channel</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;schema::MqType S_MQ_TYPE_OR_NONE, bool S_TRANSMIT_NATIVE_HANDLES, typename Mdt_payload &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname"><a class="el" href="classipc_1_1session_1_1Session__base.html#a26d038e14e3c0e461e76de88c4ce76c5">Master_structured_channel</a>* <a class="el" href="classipc_1_1session_1_1Session__base.html">ipc::session::Session_base</a>&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher::m_master_channel</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">private</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>The containing <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code> master channel. It shall exist until <code>*this</code> is gone. </p>

<p class="definition">Definition at line <a class="el" href="session__base_8hpp_source.html#l00637">637</a> of file <a class="el" href="session__base_8hpp_source.html">session_base.hpp</a>.</p>

<p class="reference">Referenced by <a class="el" href="session__base_8hpp_source.html#l01070">ipc::session::Session_base&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher::Graceful_finisher()</a>.</p>

</div>
</div>
<a id="ab1548d77913d3e99e4f30e1dd46f8d86" name="ab1548d77913d3e99e4f30e1dd46f8d86"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ab1548d77913d3e99e4f30e1dd46f8d86">&#9670;&nbsp;</a></span>m_opposing_session_done</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;schema::MqType S_MQ_TYPE_OR_NONE, bool S_TRANSMIT_NATIVE_HANDLES, typename Mdt_payload &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">boost::promise&lt;void&gt; <a class="el" href="classipc_1_1session_1_1Session__base.html">ipc::session::Session_base</a>&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher::m_opposing_session_done</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">private</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>A promise whose fulfillment is a necessary and sufficient condition for <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#af441f45ce1ed7b890c3ab77d959f8830" title="The reason Graceful_finisher exists, this method must be called at the start of *_session_impl dtor; ...">on_dtor_start()</a> returning (letting <code><a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">Session</a></code> dtor complete). </p>
<p >It is fulfilled once the <a class="el" href="classipc_1_1session_1_1Session__base.html#a26d038e14e3c0e461e76de88c4ce76c5" title="The (internally used) session master channel is a transport::struc::Channel of this concrete type.">Master_structured_channel</a> receives <code>GracefulSessionEnd</code> from opposing side (indicating the opposing <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#af441f45ce1ed7b890c3ab77d959f8830" title="The reason Graceful_finisher exists, this method must be called at the start of *_session_impl dtor; ...">on_dtor_start()</a> has started) or got hosed (indicating we'll now never know this and must act as-if opposing <a class="el" href="classipc_1_1session_1_1Session__base_1_1Graceful__finisher.html#af441f45ce1ed7b890c3ab77d959f8830" title="The reason Graceful_finisher exists, this method must be called at the start of *_session_impl dtor; ...">on_dtor_start()</a> has started). See "Design" in our doc header. </p>

<p class="definition">Definition at line <a class="el" href="session__base_8hpp_source.html#l00647">647</a> of file <a class="el" href="session__base_8hpp_source.html">session_base.hpp</a>.</p>

<p class="reference">Referenced by <a class="el" href="session__base_8hpp_source.html#l01070">ipc::session::Session_base&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher::Graceful_finisher()</a>.</p>

</div>
</div>
<a id="acb037930b23240ecf8975e65f50f3927" name="acb037930b23240ecf8975e65f50f3927"></a>
<h2 class="memtitle"><span class="permalink"><a href="#acb037930b23240ecf8975e65f50f3927">&#9670;&nbsp;</a></span>m_this_session</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;schema::MqType S_MQ_TYPE_OR_NONE, bool S_TRANSMIT_NATIVE_HANDLES, typename Mdt_payload &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname"><a class="el" href="classipc_1_1session_1_1Session__base.html">Session_base</a>* const <a class="el" href="classipc_1_1session_1_1Session__base.html">ipc::session::Session_base</a>&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher::m_this_session</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">private</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>The containing <a class="el" href="classipc_1_1session_1_1Session__base.html" title="Internal type containing data and types common to internal types Server_session_impl and Client_sessi...">Session_base</a>. It shall exist until <code>*this</code> is gone. </p>

<p class="definition">Definition at line <a class="el" href="session__base_8hpp_source.html#l00631">631</a> of file <a class="el" href="session__base_8hpp_source.html">session_base.hpp</a>.</p>

<p class="reference">Referenced by <a class="el" href="session__base_8hpp_source.html#l01070">ipc::session::Session_base&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher::Graceful_finisher()</a>.</p>

</div>
</div>
<hr/>The documentation for this class was generated from the following file:<ul>
<li>session/detail/<a class="el" href="session__base_8hpp_source.html">session_base.hpp</a></li>
</ul>
</div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 11 2025 20:02:26 for Flow-IPC by&#160;<a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.4
</small></address>
</body>
</html>
